package com.fatgirl.load
{
	import com.fatgirl.load.loadStrategy.ILoadStrategy;
	import com.fatgirl.utils.binding.DataBinding;
	
	import flash.display.Bitmap;
	import flash.display.MovieClip;
	import flash.events.TimerEvent;
	import flash.utils.ByteArray;
	import flash.utils.Timer;
	import flash.utils.getTimer;
	
	
	/**
	 *  
	 * 加载器策略工厂
	 * 添加排队机制进去
	 * 让工厂更简易化些、队列化加载
	 * 只能一个一个的进行加载并且调用其回调方法
	 * 若中间有加载出错、超时问题，需要在控制层进行有选择的  或略 或者重新加载
	 * @author iceman
	 * 
	 */
	public final class LoadFactory implements ILoadFactory
	{

		private var m_LoadSuffixList:Array;
		
		
		private var m_LoadList:Vector.<String>;
		private var m_bLoading:Boolean =  false;//是否在加载中
		private var m_url:String;//当前正在加载的URL
		private var m_LoadDataArray:Array;//加载过的数据
		private var m_afreshUrl:Array;//重新加载 定制的URL
		private var m_nowLoadStrategy:ILoadStrategy;//当前正在使用的加载器
		
		private var m_name:String;//加载器名
		
		private static var s_LoadFactoryList:Array = new Array;//存储所有工厂实例
		
		private var m_DelayTimer:Timer;//缓慢加载定时器
		private var m_nowLength:int = 0;//当前资源个数
		private var m_maxLength:int = 0;//最大资源长度,默认为0 不进行限制
		private var m_LoadDataArrayClone:Array;//加载过的数据
		
		private var m_host:String = "";//加载主机地址,默认本地
		public function LoadFactory(_name:String)
		{
			if(s_LoadFactoryList[_name]) throwError(this,FatError.SINGLETON_CLASS);
			m_LoadSuffixList = new Array;
			m_LoadDataArray = new Array;
			m_LoadDataArrayClone = new Array;
			m_LoadList = new Vector.<String>;
			m_afreshUrl = new Array;
			m_name = _name;
			m_DelayTimer = new Timer(100,1);//默认100毫秒
			m_DelayTimer.addEventListener(TimerEvent.TIMER_COMPLETE,timeDelay);
		}

		/**
		 * 设置 获取 资源主机地址 
		 * @return 
		 * 
		 */
		public function get host():String
		{
			return m_host;
		}

		public function set host(value:String):void
		{
			m_host = value;
		}

		/**
		 * 获取一个已经存在的实例 
		 * @param _name
		 * @return 
		 * 
		 */
		public static function getInstance(_name:String):LoadFactory
		{
			if(s_LoadFactoryList[_name])
				return s_LoadFactoryList[_name] as LoadFactory;
			return s_LoadFactoryList[_name] = new LoadFactory(_name);
		}
		/**
		 * 添加 加载后缀策略 
		 * @param _suffix 后缀名
		 * @param _loadClass 使用加载器的类
		 * 
		 */
		public function addLoadSuffixStrategy(_suffix:String,_loadClass:Class):void
		{
			if(_suffix==null)
			{
				throwError(this,FatError.VALUE_IS_NULL,"addLoadSuffixStrategy");
			}
			m_LoadSuffixList[_suffix] = _loadClass;
		}
		public function getData(_url:String):LoadData
		{
			_url = m_host+_url;
			var t_LoadData:LoadData =  m_LoadDataArray[_url] as LoadData;
			if(t_LoadData)
			{
				t_LoadData.loadUseTime = getTimer();
				return t_LoadData;
			}
			m_nowLength++;
			t_LoadData = new LoadData;
			t_LoadData.loadUseTime = getTimer();
			m_LoadDataArray[_url] = t_LoadData;
			if(m_bLoading)//正在加载中，加入队列
			{
				m_LoadList.push(_url);
				return t_LoadData;
			}
			if(m_afreshUrl[_url])//如果有被重定向的加载 使用从定向后的地址
			{
				_url = m_afreshUrl[_url];
			}
			startLoad(_url);
			return t_LoadData;
		}
		/**
		 * 清理掉加载过的数据缓存 
		 * @param _url 目的项
		 * 
		 */
		public function clearLoadedData(_url:String):void
		{
			_url = m_host+_url;
			if(m_LoadDataArray[_url])
			{
				(m_LoadDataArray[_url] as LoadData).destroy();
				m_LoadDataArray[_url] = null;
				delete m_LoadDataArray[_url];
				m_nowLength--;
				ftrace(this,"销毁："+_url);
			}
			
		}
		/**
		 *  
		 * 终止所有 加载项
		 */
		public function unloadAll():void
		{
			m_bLoading = false;
			if(m_nowLoadStrategy)
			{
				m_nowLoadStrategy.unLoad();
				m_nowLoadStrategy = null;
			}
			while(m_LoadList.length)
			{
				m_LoadList.shift();
			}
			ftrace(this,m_name+" 终止所有加载项..........")
		}
		/**
		 * 重新加载 
		 * @param _oldUrl  原始地址
		 * @param _newUrl  新地址
		 * @param _LoadController 加载控制器
		 * 
		 */
		private function afreshLoad(_oldUrl:String,_newUrl:String):void
		{
			_oldUrl = m_host + _oldUrl;
			_newUrl = m_host + _newUrl;
			m_bLoading = false;
			if(m_nowLoadStrategy)
			{
				m_nowLoadStrategy.unLoad();
				m_nowLoadStrategy = null;
			}
			m_afreshUrl[_oldUrl] = _newUrl;
			ftrace(this,m_name+" 由于加载超时重新加载：_oldUrl="+_oldUrl+"_newUrl="+_newUrl);
			startLoad(_newUrl);
		}
		/**
		 * 开始加载 
		 * @param _url  加载地址
		 * @param _LoadController 加载控制器对象
		 * 
		 */
		private function startLoad(_url:String):void
		{
			var t_LoadStrategy:ILoadStrategy;
			var t_url:String = _url.split("?")[0];
			var t_arr:Array = t_url.split(".");
			var t_suffix:String = t_arr[t_arr.length-1];
			if(m_LoadSuffixList[t_suffix]!=null)
			{
				t_LoadStrategy = new (m_LoadSuffixList[t_suffix] as Class);
			}
			else
			{
				throwError(this,FatError.LOAD_NOHAS_SUFFIX,_url);
			}
			m_url = _url;
			m_bLoading = true;
			m_nowLoadStrategy = t_LoadStrategy;
			var t_loadData:LoadData = m_LoadDataArray[_url] as LoadData;
			t_LoadStrategy.loadData = t_loadData;
			DataBinding.binding(this,"goOnLoad",t_loadData,"loadResultType");
			t_LoadStrategy.load(_url);
			//ftrace(this,m_name+" new开始加载："+m_url);
		}
		/**
		 * 继续加载 
		 * 
		 */
		public function goOnLoad(_result:int):void
		{
			if(_result == LoadData.LOAD_COMPLETE || _result == LoadData.LOAD_IO_ERROR)
			{
				DataBinding.removeBingding(this,"goOnLoad",m_LoadDataArray[m_url],"loadResultType");
				testLoadDataLenght(m_LoadDataArray[m_url]);//检查长度
				m_DelayTimer.start();
			}
		}
		/**
		 * 设置系统暂停时间间隔 
		 * @param _delay
		 * 
		 */
		public function setDelayTime(_delay:Number):void
		{
			if(m_DelayTimer)
			{
				m_DelayTimer.reset();
				m_DelayTimer.removeEventListener(TimerEvent.TIMER_COMPLETE,timeDelay);
			}
			m_DelayTimer = new Timer(_delay,1);
			m_DelayTimer.addEventListener(TimerEvent.TIMER_COMPLETE,timeDelay);
		}
		/**
		 * 加载工厂存储个数 
		 * @return 
		 * 
		 */
		public function getDatasLength():int
		{
			return m_nowLength;
		}
		/**
		 * 设置最大存储个数 
		 * @param _maxLength 默认为0 不限制
		 * 
		 */
		public function setDatasLength(_maxLength:int):void
		{
			m_maxLength = _maxLength;
		}
		/**
		 * 超长销毁 
		 * 
		 */
		private function testLoadDataLenght(_loadData:LoadData):void
		{
			if(!m_maxLength) return;//为0或者负数不限制长度
			m_LoadDataArrayClone.push(_loadData);
			if(m_LoadDataArrayClone.length>m_maxLength)
			{
				m_LoadDataArrayClone.sortOn("loadUseTime",Array.NUMERIC);
				for(var i:int = 0;i<int(m_maxLength/3);i++)//目前销毁个数为定长1/3
				{
					var t_loadData:LoadData = m_LoadDataArrayClone.shift();
					clearLoadedData(t_loadData.url);
				}
			}
		}
		/**
		 * 设置系统等待时间 
		 * @param e
		 * 
		 */
		private function timeDelay(e:TimerEvent):void
		{
			m_DelayTimer.reset();
			m_bLoading = false;
			if(m_LoadList.length>0) startLoad(m_LoadList.shift());
		}
	}
}
